package com.scheduler.utils.thread;

import com.scheduler.utils.trace.Slf4jMdcUtil;
import com.scheduler.utils.trace.TraceUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;

@Slf4j
public class ThreadUtil {

    /**
     * 包装正常执行的runnable，主要实现租户ID、traceId从主线程写入到子线程
     *
     * @param runnable 正常执行的runnable
     * @return 包装后的runnable
     */
    public static Runnable wrapperRunnableForSubThread(Runnable runnable) {
        String traceId = TraceUtil.getTraceId();
        return () -> {
            try {
                Slf4jMdcUtil.appendMDCWithTraceId(traceId);
                runnable.run();
            } finally {
                Slf4jMdcUtil.clearMDCAndComplete();
            }
        };
    }

    /**
     * 包装正常执行的callable，主要实现租户ID、traceId从主线程写入到子线程
     *
     * @param callable 正常执行的callable
     * @return 包装后的runnable
     */
    public static <V> Callable<V> wrapperCallableForSubThread(Callable<V> callable) {
        String traceId = TraceUtil.getTraceId();
        return () -> {
            try {
                Slf4jMdcUtil.appendMDCWithTraceId(traceId);
                return callable.call();
            } finally {
                Slf4jMdcUtil.clearMDCAndComplete();
            }
        };
    }

    /**
     * 包装 Runnable，确保不会抛出异常，这通常在调度线程池中很有用
     *
     * @param runnable 原始 runnable
     * @return 包装后的 runnable
     */
    public static Runnable wrapperRunnableForNoThrowable(Runnable runnable) {
        return () -> {
            try {
                runnable.run();
            } catch (Throwable t) {
                log.error("执行异常", t);
            }
        };
    }
}
